﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Windows.Forms;
using NmbpProject2.BusinessLayer;
using NmbpProject2.DboClasses;

namespace NmbpProject2.PresentationLayer
{
    public partial class CompetitionForm : Form
    {
        #region "*** Private variables ***"

        //komponenta koja zove logiku za rad s objektom Competition tipa
        private CompetitionBL _compLogic = new CompetitionBL();

        #endregion

        #region "*** Constructors ***"

        public CompetitionForm()
        {
            InitializeComponent();

            frmDataBind();
        }

        #endregion

        #region "*** Event handlers ***"

        private void dgvCompetitions_SelectionChanged(object sender, EventArgs e)
        {
            compDataBind();
            tabControl1.SelectTab(0);
        }

        private void btnSelectedDelete_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("This will delete all associated applications.\nAre You sure?", "Confirm delete",
                                MessageBoxButtons.YesNo,
                                MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
            {
                for (int i = 0; i < dgvCompetitions.SelectedRows.Count; i++)
                {
                    _compLogic.deleteCompetition((Competition)dgvCompetitions.SelectedRows[i].DataBoundItem);
                }
            }
            frmRefresh();
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            if (updCompIsValid())
            {
                if (dgvCompetitions.CurrentRow != null)
                    _compLogic.updateCompetition(txtSelectedCompName.Text, dtpSelectedDate.Value,
                                                 checkedCategories(clbSelectedCategories),
                                                 checkedProgLang(clbSelectedProgLang),
                                                 (Competition)dgvCompetitions.CurrentRow.DataBoundItem);
                frmRefresh();
            }
        }

        private void btnNewClear_Click(object sender, EventArgs e)
        {
            clearNewCompForm();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (newCompIsValid())
            {
                _compLogic.newCompetition(txtNewName.Text, dtpNewDate.Value, checkedCategories(clbNewCategories),
                                          checkedProgLang(clbNewProgLang));
                frmRefresh();
                clearNewCompForm();
            }
        }

        private void lbApplications_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbApplications.SelectedIndex != -1)
            {
                var application = (CompApplication)lbApplications.SelectedItem;
                lbCategories.DataSource = application.Categories;
                lbCategories.Refresh();

                lbLanguages.DataSource = application.ProgLanguages;
                lbLanguages.Refresh();
            }
        }

        private void txtFilter_TextChanged(object sender, EventArgs e)
        {
            filter();
        }

        private void btnFilterClear_Click(object sender, EventArgs e)
        {
            txtFilter.Clear();
            filter();
        }

        #endregion

        #region "*** Private methods ***"

        /// <summary>
        /// uvodni databind, puni check list boxeve, dgv.
        /// </summary>
        private void frmDataBind()
        {
            var compList = _compLogic.allCompetitions("");

            //dgv bind
            dgvCompetitions.DataSource = compList;
            dgvCompetitions.Refresh();
            dgvCompetitions.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            dgvCompetitions.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            dgvCompetitions.Columns[1].DefaultCellStyle.Format = "dd. MM. yyyy. ";

            //clb binds
            var progLangs = new ProgLanguageBL().getAllLangs();
            foreach (ProgLanguage lang in progLangs)
            {
                clbNewProgLang.Items.Add(lang);
                clbSelectedProgLang.Items.Add(lang);
            }
            var categories = new CategoryBL().getAllCategories();
            foreach (Category category in categories)
            {
                clbNewCategories.Items.Add(category);
                clbSelectedCategories.Items.Add(category);
            }
        }

        /// <summary>
        /// osvjezavanje dgv-a
        /// </summary>
        private void frmRefresh()
        {
            filter();
        }

        /// <summary>
        /// fja za popunjavanje podataka o selektiranom natjecanju
        /// </summary>
        private void compDataBind()
        {
            if (dgvCompetitions.CurrentRow != null)
            {
                //dohvatimo objekt
                var comp = (Competition)dgvCompetitions.CurrentRow.DataBoundItem;
                //napunimo podatke u txt boxeve
                txtSelectedCompName.Text = comp.Name;
                dtpSelectedDate.Value = comp.Date;
                //clb checkiraju adekvatna polja.
                clearCLB(clbSelectedCategories);
                if (comp.Categories != null)
                    foreach (var category in comp.Categories)
                    {
                        for (int i = 0; i < clbSelectedCategories.Items.Count; i++)
                        {
                            if (category.ToString() == clbSelectedCategories.Items[i].ToString())
                            {
                                clbSelectedCategories.SetItemChecked(i, true);
                                break;
                            }
                        }
                    }
                if (clbSelectedProgLang != null)
                {
                    clearCLB(clbSelectedProgLang);
                    if (comp.ProgLanguages != null)
                        foreach (var language in comp.ProgLanguages)
                        {
                            for (int i = 0; i < clbSelectedProgLang.Items.Count; i++)
                            {
                                if (language.ToString() == clbSelectedProgLang.Items[i].ToString())
                                {
                                    clbSelectedProgLang.SetItemChecked(i, true);
                                    break;
                                }
                            }
                        }
                }

                //napunimo aplikante i podatke o njima u lb-ove
                lbApplications.DataSource = comp.Applications;
                lbApplications.Refresh();
            }
        }

        /// <summary>
        /// pomocna fja, cisti kvacice iz predanog clb
        /// </summary>
        /// <param name="clb">predani clb</param>
        private void clearCLB(CheckedListBox clb)
        {
            for (int i = 0; i < clb.Items.Count; i++)
            {
                clb.SetItemChecked(i, false);
            }
        }

        /// <summary>
        /// pomocna fja, prazni polja i clb za unos novog natjecanja
        /// </summary>
        private void clearNewCompForm()
        {
            txtNewName.Text = "";
            dtpSelectedDate.Value = DateTime.Now;
            clearCLB(clbNewCategories);
            clearCLB(clbNewProgLang);
        }

        /// <summary>
        /// provjera ispravnosti unesenih podataka
        /// </summary>
        /// <returns>vraca true kad su podaci ispravni</returns>
        private bool newCompIsValid()
        {
            if (txtNewName.Text == "" || txtNewName.Text.Length < 3)
            {
                MessageBox.Show("Event name is too short or missing.", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Stop);
                return false;
            }
            if (_compLogic.isDuplicate(txtNewName.Text, dtpNewDate.Value))
            {
                MessageBox.Show("Event with the same name on the same date already exists.", "Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Stop);
                return false;
            }


            return true;
        }

        /// <summary>
        /// provjera ispravno unesenog imena kod izmjene
        /// natjecanja odabranog u listboxu
        /// </summary>
        /// <returns>vraca true za ispravan unos</returns>
        private bool updCompIsValid()
        {
            if (txtSelectedCompName.Text == "" || txtSelectedCompName.Text.Length < 3)
            {
                MessageBox.Show("New event name is too short or missing.", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Stop);
                return false;
            }
            return true;
        }

        /// <summary>
        /// fja koja vraca objekte tipa Category checkirane u predanom CLB
        /// </summary>
        /// <param name="clb">odabrani clb</param>
        /// <returns>lista objekata tipa Category</returns>
        private List<Category> checkedCategories(CheckedListBox clb)
        {
            var list = new List<Category>();
            foreach (object item in clb.CheckedItems)
            {
                list.Add((Category)item);
            }
            return list;
        }

        /// <summary>
        /// fja koja vraca objekte tipa progLanguage checkirane u predanom CLB
        /// </summary>
        /// <param name="clb">odabrani clb</param>
        /// <returns>lista objekata tipa progLanguage</returns>
        private List<ProgLanguage> checkedProgLang(CheckedListBox clb)
        {
            var list = new List<ProgLanguage>();
            foreach (object item in clb.CheckedItems)
            {
                list.Add((ProgLanguage)item);
            }
            return list;
        }

        private void filter()
        {
            var compList = _compLogic.allCompetitions(txtFilter.Text);
            dgvCompetitions.DataSource = compList;
            dgvCompetitions.Refresh();
        }


        /// <summary>
        /// Convert a List{T} to a DataTable.
        /// </summary>
        private DataTable ToDataTable<T>(List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var prop in props)
            {
                tb.Columns.Add(prop.Name, prop.PropertyType);
            }

            foreach (var item in items)
            {
                var values = new object[props.Length];
                for (var i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }
                tb.Rows.Add(values);
            }
            return tb;
        }


        #endregion

    }
}